%% Author : lichuang
-module(echubby_quorum_manager).

-behaviour(gen_server).
-include("echubby.hrl").
-include("quorum_peer_pb.hrl").
-export([start_link/1]).
-export([init/1,
	 handle_call/3,
	 handle_cast/2,
	 handle_info/2,
	 terminate/2,
	 code_change/3]).

start_link(ConfigFile) ->
  gen_server:start_link({local, ?MODULE}, ?MODULE, [ConfigFile], []).

init(ConfigFile) ->
  ?INFO_MSG("parse config file success ~p", [ConfigFile]),
  case echubby_config:parse_file(ConfigFile) of
    {ok} ->
      ?INFO_MSG("parse config file ~p success", [ConfigFile]);
    {error} ->
      ?INFO_MSG("parse config file ~p fail", [ConfigFile]),
      exit(parse_config_file_fail)
  end,
  {ok, {}}.

handle_cast(connect_to_other_servers, _State) ->
  ServerInfoList = echubby_config:get_other_server_info(),
  ?DEBUG_MSG("other server info:~p", [ServerInfoList]),
  lists:map(fun connect_to_server/1, ServerInfoList),
  {noreply, _State};
handle_cast(#notification{leader = Leader,
			  gxid   = Gxid,
			  epoch  = Epoch,
			  state	 = State,
			  server_id = ServerId}, _State) ->
 ?INFO_MSG("receive msg ~p", [ServerId]),
 lists:foldl(fun send_notification/2, 
	    #notification{leader = Leader,
			  gxid   = Gxid,
			  epoch  = Epoch,
		          state	 = State,
		          server_id = ServerId},
	    get()),
 {noreply, State};
handle_cast(_Req, State) ->
  {noreply, State}.

handle_call(my_server_info, _From, State) ->
  {reply, {ok, echubby_config:get_my_server_info()}, State};
handle_call(_Req, _From, State) ->
  {noreply, State}.

handle_info(_Info, State) ->
    {noreply, State}.

terminate(_Reason, _State) ->
  ok.

code_change(_OldVsn, State, _Extra) ->
      {ok, State}.

send_notification(#notification{leader = Leader,
				gxid   = Gxid,
				epoch  = Epoch,
				state	 = State,
				server_id = ServerId},
				{_, Pid}) ->
  gen_server:cast(Pid, #notification{leader = Leader,
				     gxid   = Gxid,
				     epoch  = Epoch,
				     state  = State,
				     server_id = ServerId}).

connect_to_server(ServerInfo) ->
  ?DEBUG_MSG("other server info:~p", [ServerInfo]),
  {Id, _, _} = ServerInfo,
  {ok, Pid} = gen_server:start_link(
    echubby_quorum_connector,
    [Id], []),
  put(Id, Pid),
  gen_server:cast(Pid, {connect_to_server, ServerInfo}),
  {ok}.
